package com.sirui.jpa.service.impl;

import com.sirui.jpa.dynamicquery.DynamicQuery;
import com.sirui.jpa.model.JpaStudent;
import com.sirui.jpa.model.Student;
import com.sirui.jpa.repository.StudentRepository;
import com.sirui.jpa.service.IStudentService;
import lombok.extern.apachecommons.CommonsLog;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;

@Service
@CommonsLog
public class StudentServiceImpl implements IStudentService {

    final static SimpleDateFormat sdf = new SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    final static String startTime = sdf.format(new Date());
    @Autowired
    private DynamicQuery dynamicQuery;

    @Autowired
    private StudentRepository studentRepository;

    //批量插入
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    @Autowired
    private EntityManager entityManager;

    @Override
    public List<Object[]> listStudent() {
        String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM t_jpa_student s,t_jpa_class c";
        List<Object[]> list = dynamicQuery.nativeQueryList(nativeSql, new Object[]{});
        return list;
    }

    @Override
    public List<Student> listStudentModel() {
        String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM t_jpa_student s,t_jpa_class c";
        List<Student> list = dynamicQuery.nativeQueryListModel(Student.class, nativeSql);
        return list;
    }

    @Override
    public List<Map<Object, Object>> listStudentMap() {
        String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM t_jpa_student s,t_jpa_class c";
        List<Map<Object, Object>> list = dynamicQuery.nativeQueryListMap(nativeSql, new Object[]{});
        return list;
    }

    @Override
    public void batchSave() {
        List<JpaStudent> list = new ArrayList<JpaStudent>();
        list.add(new JpaStudent("1", "张三", 21));
        list.add(new JpaStudent("1", "李四", 22));
        list.add(new JpaStudent("1", "王二麻子", 23));
        SqlParameterSource[] beanSources = SqlParameterSourceUtils.createBatch(list.toArray());
        String sql = "INSERT INTO t_jpa_student(class_id,name,age) VALUES (:classId,:name,:age) ";
        namedParameterJdbcTemplate.batchUpdate(sql, beanSources);
    }

    @Override
    public void batchSave(List<JpaStudent> list) {
        SqlParameterSource[] beanSources = SqlParameterSourceUtils.createBatch(list.toArray());
        String sql = "INSERT INTO t_jpa_student(class_id,name,age) VALUES (:classId,:name,:age) ";
        namedParameterJdbcTemplate.batchUpdate(sql, beanSources);
    }

    @Override
    public void statsDemo() throws Exception {
        CountDownLatch latch = new CountDownLatch(5);// 两个赛跑者
        Stats stats1 = new Stats("任务A", 1000, latch);
        Stats stats2 = new Stats("任务B", 2000, latch);
        Stats stats3 = new Stats("任务C", 2000, latch);
        Stats stats4 = new Stats("任务D", 2000, latch);
        Stats stats5 = new Stats("任务E", 2000, latch);
        stats1.start();//任务A开始执行
        stats2.start();//任务B开始执行
        stats3.start();//任务C开始执行
        stats4.start();//任务D开始执行
        stats5.start();//任务E开始执行
        latch.await();// 等待所有人任务结束
        System.out.println("所有的统计任务执行完成:" + sdf.format(new Date()));
    }

    @Override
    public List<JpaStudent> listStudent(int pageNum, int pageSize) {
        Pageable page = PageRequest.of(pageNum, pageSize);
        Page<JpaStudent> pageBean = studentRepository.findAll(page);
        return pageBean.getContent();
    }


    @Override
    @Transactional
    public Optional<JpaStudent> findOne(Specification<JpaStudent> specification) {
        Optional<JpaStudent> optional = studentRepository.findOne(specification);
        JpaStudent jpaStudent = optional.get();

        Session session1 = entityManager.unwrap(Session.class);
        session1.evict(jpaStudent);

        //HibernateEntityManager hibernateEntityManager = (HibernateEntityManager) entityManager;
        //Session session = hibernateEntityManager.getSession();
        //session.evict(jpaStudent);

        jpaStudent.setName("zhao7");
        return optional;
    }

    static class Stats extends Thread {
        String statsName;
        int runTime;
        CountDownLatch latch;

        public Stats(String statsName, int runTime, CountDownLatch latch) {
            this.statsName = statsName;
            this.runTime = runTime;
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                System.out.println(statsName + " do stats begin at " + startTime);
                //模拟任务执行时间
                Thread.sleep(runTime);
                System.out.println(statsName + " do stats complete at " + sdf.format(new Date()));
                latch.countDown();//单次任务结束，计数器减一
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
